home *** CD-ROM | disk | FTP | other *** search
/ Just Call Me Internet / Just Call Me Internet.iso / prog / atari / c / nos042_s / dirutil.c < prev    next >
C/C++ Source or Header  |  1994-09-16  |  12KB  |  427 lines

  1. /*----------------------------------------------------------------------------
  2.     dirutil.c - ATARI ST directory reading routines
  3.  
  4.     ST NOS Version by David Nash, dnash@chaos.demon.co.uk
  5.  
  6.     21.08.94 DFN - Remove blank padding in short, single column list.
  7.  
  8. ----------------------------------------------------------------------------*/
  9.  
  10. #include <stdio.h>
  11. #include <ctype.h>
  12. #include <osbind.h>
  13. #include <dos.h>
  14. #include <errno.h>
  15. #include <sys/types.h>
  16. #include <sys/stat.h>
  17. #include <dirent.h>
  18. #include <unistd.h>
  19.  
  20. #include "global.h"
  21. #include "commands.h"
  22.  
  23. #undef   time                                        /* remove macro from global.h     */
  24.  
  25. static struct    FILEINFO    info;                    /* file information = dta            */
  26.  
  27. static void format_dir(char *, struct stat);
  28. static void format_fname(char *, char *, char);
  29. static void diskfree(FILE *, int, int);
  30. static void format_dirent(char *line, char *name, struct stat *st_buf, int full);
  31.  
  32.        int    getdir(char *, int full, FILE *);
  33.        void path_u2d(char *);
  34.        
  35.  
  36. #define NULLSORT (struct dirsort *)0
  37.  
  38. #ifndef FALSE
  39. #define FALSE (0)
  40. #endif
  41.  
  42. #ifndef TRUE
  43. #define TRUE (!0)
  44. #endif
  45.  
  46. #define DIR_NAMES    256
  47. #define PATH_LEN    256
  48. #define FILE_L     13
  49.  
  50.  
  51. /*---------------------------------------------------------------------------
  52.     dir - Create a directory listing in a temp file and return the
  53.             resulting file descriptor. If full == 1, give a full listing;
  54.             else return just a list of names.
  55. ---------------------------------------------------------------------------*/
  56.  
  57. FILE *dir(char *path, int full) {
  58.  
  59.     FILE *fp;
  60.  
  61.     if ((fp = tmpfile()) != NULLFILE) {
  62.         getdir(path, full, fp);
  63.         rewind(fp);
  64.     }
  65.  
  66.     return fp;
  67. }
  68.  
  69. /*---------------------------------------------------------------------------
  70.     filedir - wildcard filename lookup
  71. ---------------------------------------------------------------------------*/
  72.  
  73. void filedir(char *name, int times, char *ret_str) {
  74.     
  75.     char *cp, *cp1;
  76.     
  77.     Fsetdta(&info);    /* Set disk transfer address */
  78.  
  79.     path_u2d(name);                                /* convert path seperators            */
  80.     
  81.     /* Find matching file */
  82.  
  83.     if (times == 0 ? Fsfirst(name, 0x11) : Fsnext())    /* include r/o and dir  */    
  84.         info.name[0] = '\0';                        /* file name not found                */
  85.         
  86.     /* Copy result to output, forcing to lower case */
  87.  
  88.     for(cp = ret_str, cp1 = info.name; cp1 < &info.name[13] && *cp1 != '\0'; )
  89.         *cp++ = (char)tolower(*cp1++);
  90.     *cp = '\0';
  91. }
  92.  
  93.  
  94. /*---------------------------------------------------------------------------
  95.     getdir - do a directory list to the stream 
  96.                 full = 0 -> short form, list of valid file names seperated by '\n'
  97.                          1 -> long form, filenames and statistics
  98.                         -1 -> multi-column short
  99. ---------------------------------------------------------------------------*/
  100.  
  101. int getdir(char *path, int full, FILE *file) {
  102.  
  103.     int     indx = 0, i = 0;
  104.     int    no_files = 0;
  105.     int    count = 0;
  106.     int    drive_n;
  107.     int   flag = 0;
  108.     int    cols = 1;                                
  109.     
  110.     char    drive_c;
  111.     char    *path_p, *path_q;                            /* pointer into path string    */
  112.     char     line_buf[50];                                /* for long dirlist                 */
  113.     char    fq_path[128];                                /* fully quilified path            */
  114.     char  fq_name[128];                                /* fully qualified name            */
  115.  
  116.     char  **name_p;                                    /* pointers to file names        */
  117.     char  *names;                                        /* array of file names            */
  118.     char    *name_ptr;                                    /* pointer into names array    */
  119.  
  120.     struct stat st_buf;                                /* buffer for stat results        */
  121.     struct stat    *st_buf_p = 0;                        /* pointer to stat buffer        */
  122.     
  123.     struct dirent *dp;                                /* directory entry pointer        */
  124.     DIR    *dir;                                            /* directory stream pointer    */
  125.  
  126.     
  127.     path_u2d(path);                                    /* convert path seperators        */
  128.  
  129.     if (full > 0)
  130.         cols = 2;                                        /* long listing format            */
  131.     else if (full < 0)
  132.         cols = 5;                                        /* multi column wide format    */
  133.     else
  134.         cols = 1;                                        /* one column short list        */
  135.  
  136.         
  137.     /*    Analyse the path components                                                        */
  138.     
  139.     if (path[1] == ':') {
  140.         drive_c = path[0];                            /* set drive letter                */
  141.         drive_n = toupper(path[0]) - 'A' + 1;    /* set drive number, a=1        */
  142.         path_p  = path + 2;                            /* point past drive letter        */
  143.     }
  144.     else {
  145.         drive_n = Dgetdrv() + 1;                    /* get default drive, a=1        */
  146.         drive_c = drive_n + 'A' - 1;                /* default drive letter            */
  147.         path_p  = path;                                /* point to full path            */
  148.     }
  149.  
  150.     if (*path_p == '.')
  151.         path++;                                            /* remove .  (current dir)        */    
  152.     if (*path_p == '.')
  153.         path_p++;                                        /* remove .. (previous dir)    */    
  154.  
  155.     if (path[0] == '\\')                                /* process absolute path        */
  156.         sprintf(fq_path, "%c:%s\0", drive_c, path_p);
  157.     else if (path[1] == ':' && path[2] == '\\')
  158.         sprintf(fq_path, "%s\0", path);
  159.     else {                                                /* process relative path        */
  160.         Dgetpath(fq_name, drive_n);                /* get current directory         */
  161.             sprintf(fq_path, "%c:%s\\%s\0", drive_c, fq_name, path_p);
  162.     }
  163.  
  164.     if (fq_path[strlen(fq_path) -1] != '\\')        
  165.         strcat(fq_path, "\\");                        /* must end in \                    */
  166.  
  167.  
  168.     /* Strip out duplicate '\' characters                                                */
  169.     
  170.     for (path_p = path_q = fq_path; *path_p; path_p++) {
  171.         if (flag)                                         /* alraedy got a slash            */
  172.             if (*path_p == '\\')
  173.                 continue;                                /* we dont't want another        */
  174.             else
  175.                 flag = 0;                                /* normal char, clear flag        */
  176.         else                                                /* last char was normal            */
  177.             if (*path_p == '\\')
  178.                 flag = 1;                                /* got a slash, set flag        */
  179.         *path_q++ = *path_p;                            /* copy the char                    */
  180.     }
  181.  
  182.     *path_q = '\0';                                    /* force end of string            */
  183.  
  184.     
  185.     /* Process the dirctory                                                      */
  186.     
  187.     if ((dir = opendir(fq_path)) == NULL) {    /* open the directory            */
  188.         fprintf(file, "Path %s not found \n", path); 
  189.         return -1;                                        /* error, directory not found    */
  190.     }
  191.  
  192.     while (readdir(dir))                                /* count number of entries        */
  193.         count++;
  194.  
  195.     count += 10;                                        /* add fudge factor                */
  196.     rewinddir(dir);                                    /* reset directory pointer        */
  197.  
  198.     if ((names = (char *)calloc(count * FILE_L, sizeof(char))) == NULL) {
  199.         closedir(dir);
  200.         tprintf("getdir: calloc failed for names \n");
  201.         return -1;
  202.     }
  203.  
  204.     if ((name_p = (char **)calloc(count, sizeof(char *))) == NULL) {
  205.         free(names);
  206.         closedir(dir);
  207.         tprintf("getdir: calloc failed for name_p \n");
  208.         return -1;
  209.     }
  210.     
  211.     name_ptr = names;                                    /* initilise the pointer        */
  212.     
  213.     while (dp = readdir(dir)) {
  214.         if (dp->d_name[0] == '.') 
  215.             continue;                                    /* ignore 'hidden' files        */
  216.  
  217.         strncpy(name_ptr, dp->d_name, dp->d_reclen);
  218.         name_p[indx] = name_ptr;                    /* setup pointer                    */
  219.         name_ptr += dp->d_reclen + 1;
  220.         indx++;
  221.     }                                                        /*    END of while loop                */
  222.  
  223.     if (closedir(dir) != 0)                            /* close the directory            */
  224.         tprintf("getdir: closedir failed %s \n", strerror(errno));
  225.  
  226.     no_files = indx;                                    /* save number of files            */
  227.  
  228.     tqsort(name_p, no_files);                        /* sort the pointers                */
  229.  
  230.  
  231.     /* Format and write the output                                         */
  232.     
  233.     for (indx = 0; indx < no_files; indx++) {
  234.         if (full > 0) {
  235.             st_buf_p = &st_buf;                        /* may have been reset            */
  236.             sprintf(fq_name, "%s%s\0", fq_path, name_p[indx]);
  237.  
  238.             if (stat(fq_name, st_buf_p) == -1) {
  239.                 st_buf_p = 0;
  240.             }
  241.         }
  242.  
  243.         format_dirent(line_buf, name_p[indx], st_buf_p, full);
  244.         fprintf(file, "%s%s", line_buf, (++i % cols) ? "   " : "\n");
  245.     } 
  246.  
  247.     if (i % cols)
  248.         fprintf(file, "\n");
  249.  
  250.     if (full > 0)
  251.             diskfree(file, drive_n, no_files);
  252.  
  253.     free(names);                                        /* free the file name array    */
  254.     free(name_p);                                        /* free the pointer array        */
  255.  
  256.     return 0;                                            /* return OK                        */
  257. }
  258.  
  259.  
  260. /*---------------------------------------------------------------------------
  261.     format_dirent - format a directory entry
  262. ---------------------------------------------------------------------------*/
  263.  
  264. static void format_dirent( char *line, 
  265.                                    char *name, 
  266.                            struct stat *st_buf, 
  267.                            int full
  268.                          )
  269. {
  270.     char *p, *q;
  271.     char size[12];                                    /* file size                            */
  272.     char time[15];                                    /* file modification time            */
  273.     char fname[14];                                /* formatted file name                */    
  274.  
  275.     *line = '\0';                                    /* clear the output buffer            */
  276.     
  277.     for (p = name, q = fname; *p && *p != ' '; p++, q++)
  278.         *q = tolower(*p);
  279.  
  280.     *q = '\0';                                        /* terminate the string                */
  281.  
  282.     if (full == 0) {
  283.         strcpy(line, fname);
  284.         return;                                        /* short, NL terminated list        */
  285.     }
  286.     
  287.     if (full < 0) {                                /* short multi line format         */
  288.         sprintf(line, "%-13s\0", fname);        
  289.         return;
  290.     }
  291.                     
  292.     if (S_ISDIR(st_buf->st_mode))    {
  293.         *q++ = '/';
  294.         sprintf(size, "  ");                       /* no size for dir                    */
  295.     }    
  296.     else          
  297.         sprintf(size, "%ld", st_buf->st_size);
  298.  
  299.     *q = '\0';                                        /* set EOS for file name            */
  300.     
  301.     strftime(time, sizeof(time), "%H:%M %d.%m.%y", localtime(&st_buf->st_mtime));
  302.     sprintf(line, "%8s %14s %-13s", size, time, fname); 
  303. }
  304.  
  305.  
  306. /*---------------------------------------------------------------------------
  307.     diskfree - return stats
  308. ---------------------------------------------------------------------------*/
  309.  
  310. void diskfree (FILE *file, int drv, int nfiles)
  311. {
  312.     unsigned long free_bytes  = 0;
  313.     unsigned long total_bytes = 0;
  314.     struct DISKINFO disk_info;
  315.      char s_free[11];
  316.     char s_total[11];
  317.  
  318.     fflush(stdout);                                 /* function takes a short while... */
  319.  
  320.     if (Dfree((void *)&disk_info, (short)drv) == 0)    {
  321.         free_bytes  = disk_info.bps * disk_info.spc;
  322.         total_bytes = free_bytes * disk_info.cpd;
  323.         free_bytes *= disk_info.free;
  324.     }
  325.  
  326.     sprintf(s_free, "%ld", free_bytes);
  327.     sprintf(s_total,"%ld", total_bytes);
  328.  
  329.     if (nfiles)
  330.         fprintf(file, "\n%d", nfiles);
  331.     else
  332.         fprintf(file, "No");
  333.  
  334.     fprintf(file, " file%s. %s bytes free. Disk size %s bytes.\r\n",
  335.               (nfiles == 1 ? "" : "s"), s_free, s_total);
  336. }
  337.  
  338.  
  339. /*---------------------------------------------------------------------------
  340.     Change working directory
  341. ---------------------------------------------------------------------------*/
  342.  
  343. docd(int argc, char *argv[], void *p)
  344. {
  345.     char dirname[128];
  346.  
  347.     if(argc > 1) {
  348.         path_u2d(argv[1]);                            /* convert path seperators            */
  349.         if(chdir(argv[1])){
  350.             printf("Can't change directory\n");
  351.             return 1;
  352.         }
  353.     }
  354.  
  355.     if (Dgetpath(dirname,0) == 0){
  356.         printf("%c:%s%s\n",(char) Dgetdrv()+'A',
  357.             (*dirname ? "" : "\\"),dirname);
  358.     }
  359.  
  360.     return 0;
  361. }
  362.  
  363.  
  364. /*---------------------------------------------------------------------------
  365.     dodir - List directory to console. [-]w option selects "wide" format
  366. ---------------------------------------------------------------------------*/
  367.  
  368. int __stdargs dodir(int argc, char *argv[], void *p) {
  369.     char path[PATH_LEN];
  370.     int full = 1;
  371.  
  372.     if (argc > 1 && argv[1][0] == '-' && argv[1][1] == 'w') {
  373.         full = -1;
  374.         argv++;
  375.         argc--;
  376.     }
  377.  
  378.     if (argc >= 2) {
  379.         strncpy(path, argv[1], PATH_LEN);    
  380.     } else {
  381.         strcpy(path, ".");
  382.     }
  383.  
  384.     getdir(path, full, stdout);
  385.     return 0;
  386. }
  387.  
  388.  
  389. /*---------------------------------------------------------------------------
  390.     domkd - Create directory
  391. ---------------------------------------------------------------------------*/
  392.  
  393. int domkd(int argc, char *argv[], void *p)
  394. {
  395.     if (mkdir(argv[1]) == -1)
  396.         tprintf("Can't make %s: %s\n", argv[1], strerror(errno));
  397.     return 0;
  398. }
  399.  
  400.  
  401. /*---------------------------------------------------------------------------
  402.     dormd - Remove directory
  403. ---------------------------------------------------------------------------*/
  404.  
  405. int dormd(int argc, char *argv[], void *p)
  406. {
  407.     if (rmdir(argv[1]) == -1)
  408.         tprintf("Can't remove %s: %s\n", argv[1], strerror(errno));
  409.     return 0;
  410. }
  411.  
  412.  
  413. /*---------------------------------------------------------------------------
  414.     path_u2d - convert unix style path seperators to dos style seperators
  415. ---------------------------------------------------------------------------*/
  416.  
  417. void path_u2d(char *name)
  418. {
  419.     char *p;
  420.  
  421.     for (p = name; *p; p++)
  422.         if (*p == '/')
  423.             *p = '\\';
  424.  
  425.     return;
  426. }
  427.